rockchip/rk3399: Split M0 binary into two
authorLin Huang <[email protected]>
Fri, 20 Apr 2018 07:55:21 +0000 (15:55 +0800)
committerLin Huang <[email protected]>
Tue, 15 May 2018 08:31:09 +0000 (16:31 +0800)
All the m0 code run in SRAM before, but we need to watch PMU_POWER_ST
when SOC enter into FSM, and SRAM will shutdown during this time, so
this code need run in PMUSRAM. But PMUSRAM only 8K space, we can not
put all the m0 binary into PMUSRAM, Split the M0 binary into two, dram
part still run in SRAM, and suspend part run in PMUSRAM.

Change-Id: Ie08bdf3e2b8838f12b9297fe60ab0aad219684b1
Signed-off-by: Lin Huang <[email protected]>
14 files changed:
plat/rockchip/rk3399/drivers/dram/dfs.c
plat/rockchip/rk3399/drivers/m0/Makefile
plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h
plat/rockchip/rk3399/drivers/m0/src/dram.c
plat/rockchip/rk3399/drivers/m0/src/main.c [deleted file]
plat/rockchip/rk3399/drivers/m0/src/startup.c
plat/rockchip/rk3399/drivers/m0/src/suspend.c
plat/rockchip/rk3399/drivers/pmu/m0_ctl.c
plat/rockchip/rk3399/drivers/pmu/m0_ctl.h
plat/rockchip/rk3399/drivers/pmu/pmu.c
plat/rockchip/rk3399/drivers/pmu/pmu_fw.c
plat/rockchip/rk3399/include/plat.ld.S
plat/rockchip/rk3399/include/shared/m0_param.h
plat/rockchip/rk3399/platform.mk

index 70d9423b313d82513deb8804ef32b2e5e5d93a77..e6d39a1dd8aa2a9c9e5a60def8043804b98817f8 100644 (file)
@@ -1964,9 +1964,6 @@ uint32_t dram_set_odt_pd(uint32_t arg0, uint32_t arg1, uint32_t arg2)
 
 static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
 {
-       /* set PARAM to M0_FUNC_DRAM */
-       mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_DRAM);
-
        mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON0, FBDIV(pll_div.fbdiv));
        mmio_write_32(M0_PARAM_ADDR + PARAM_DPLL_CON1,
                      POSTDIV2(pll_div.postdiv2) | POSTDIV1(pll_div.postdiv1) |
@@ -1976,6 +1973,7 @@ static void m0_configure_ddr(struct pll_div pll_div, uint32_t ddr_index)
 
        mmio_write_32(M0_PARAM_ADDR + PARAM_FREQ_SELECT, ddr_index << 4);
        dmbst();
+       m0_configure_execute_addr(M0_BINCODE_BASE);
 }
 
 static uint32_t prepare_ddr_timing(uint32_t mhz)
index f6bdbf271fe19701e0d7941c1fa0ea852f91871c..79e09f0ef71192c72c600ba32bdd09c6f9dc2efe 100644 (file)
@@ -12,6 +12,7 @@ ARCH          := cortex-m0
 
 # Build platform
 PLAT_M0                ?= rk3399m0
+PLAT_M0_PMU    ?= rk3399m0pmu
 
 ifeq (${V},0)
        Q=@
@@ -26,11 +27,10 @@ INCLUDES            += -Iinclude/ \
                           -I../../include/shared/
 
 # NOTE: Add C source files here
-C_SOURCES              := src/startup.c \
-                          src/main.c   \
-                          src/suspend.c \
-                          src/dram.c   \
+C_SOURCES_COMMON       := src/startup.c
+C_SOURCES              := src/dram.c   \
                           src/stopwatch.c
+C_SOURCES_PMU          := src/suspend.c
 
 # Flags definition
 COMMON_FLAGS           := -g -mcpu=$(ARCH) -mthumb -Wall -O3 -nostdlib -mfloat-abi=soft
@@ -54,12 +54,19 @@ define SOURCES_TO_OBJS
        $(notdir $(patsubst %.S,%.o,$(filter %.S,$(1))))
 endef
 
+SOURCES_COMMON         := $(C_SOURCES_COMMON)
 SOURCES                := $(C_SOURCES)
+SOURCES_PMU            := $(C_SOURCES_PMU)
+OBJS_COMMON            := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_COMMON)))
 OBJS                   := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES)))
+OBJS_PMU               := $(addprefix $(BUILD)/,$(call SOURCES_TO_OBJS,$(SOURCES_PMU)))
 LINKERFILE             := $(BUILD)/$(PLAT_M0).ld
 MAPFILE                        := $(BUILD)/$(PLAT_M0).map
+MAPFILE_PMU            := $(BUILD)/$(PLAT_M0_PMU).map
 ELF                    := $(BUILD)/$(PLAT_M0).elf
+ELF_PMU                        := $(BUILD)/$(PLAT_M0_PMU).elf
 BIN                    := $(BUILD)/$(PLAT_M0).bin
+BIN_PMU                        := $(BUILD)/$(PLAT_M0_PMU).bin
 LINKERFILE_SRC         := src/$(PLAT_M0).ld.S
 
 # Function definition related compilation
@@ -92,18 +99,27 @@ define MAKE_OBJS
        $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN)))
 endef
 
-.DEFAULT_GOAL := $(BIN)
+.PHONY: all
+all: $(BIN) $(BIN_PMU)
+
+.DEFAULT_GOAL := all
 
 $(LINKERFILE): $(LINKERFILE_SRC)
        $(CC) $(COMMON_FLAGS) $(INCLUDES) -P -E -D__LINKER__ -MMD -MF [email protected] -MT $@ -o $@ $<
 -include $(LINKERFILE).d
 
-$(ELF) : $(OBJS) $(LINKERFILE)
+$(ELF) : $(OBJS) $(OBJS_COMMON) $(LINKERFILE)
        @echo "  LD      $@"
-       $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS)
+       $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE) -Wl,-T$(LINKERFILE) $(OBJS) $(OBJS_COMMON)
 
-$(BIN) : $(ELF)
+%.bin : %.elf
        @echo "  BIN     $@"
        $(Q)$(OC) -O binary $< $@
 
+$(ELF_PMU) : $(OBJS_COMMON) $(OBJS_PMU) $(LINKERFILE)
+       @echo "  LD      $@"
+       $(Q)$(CC) -o $@ $(COMMON_FLAGS) $(LDFLAGS) -Wl,-Map=$(MAPFILE_PMU) -Wl,-T$(LINKERFILE) $(OBJS_PMU) $(OBJS_COMMON)
+
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_COMMON),$(1)))
 $(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES),$(1)))
+$(eval $(call MAKE_OBJS,$(BUILD),$(SOURCES_PMU),$(1)))
index 472cbc961efcced7644c312c73de1d29b81acbde..176af3ae9a68392bf1c0c9b3e89a9828614cc871 100644 (file)
@@ -25,8 +25,6 @@ typedef unsigned int uint32_t;
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 
-void handle_suspend(void);
-void handle_dram(void);
 void stopwatch_init_usecs_expire(unsigned int usecs);
 int stopwatch_expired(void);
 void stopwatch_reset(void);
index c6a9259d2ce815456a2fdb7e58713f929fc97e45..b939a9605dea26e9c8d90bce8f83546202bed9f7 100644 (file)
@@ -55,7 +55,7 @@ static void ddr_set_pll(void)
        mmio_write_32(CRU_BASE + CRU_DPLL_CON3, PLL_MODE(PLL_NORMAL_MODE));
 }
 
-void handle_dram(void)
+__attribute__((noreturn)) void main(void)
 {
        mmio_setbits_32(PHY_REG(0, 927), (1 << 22));
        mmio_setbits_32(PHY_REG(1, 927), (1 << 22));
@@ -76,4 +76,9 @@ void handle_dram(void)
        deidle_port();
        mmio_clrbits_32(PHY_REG(0, 927), (1 << 22));
        mmio_clrbits_32(PHY_REG(1, 927), (1 << 22));
+
+       mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
+
+       for (;;)
+               __asm__ volatile ("wfi");
 }
diff --git a/plat/rockchip/rk3399/drivers/m0/src/main.c b/plat/rockchip/rk3399/drivers/m0/src/main.c
deleted file mode 100644 (file)
index 0ed818d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <m0_param.h>
-#include "rk3399_mcu.h"
-
-__attribute__((noreturn)) void main(void)
-{
-       switch (mmio_read_32(PARAM_ADDR + PARAM_M0_FUNC)) {
-       case M0_FUNC_SUSPEND:
-               handle_suspend();
-               break;
-       case M0_FUNC_DRAM:
-               handle_dram();
-               break;
-       default:
-               break;
-       }
-
-       mmio_write_32(PARAM_ADDR + PARAM_M0_DONE, M0_DONE_FLAG);
-
-       for (;;)
-               __asm__ volatile ("wfi");
-}
index 68f5b2dce372c3b288de56089d641315ee31b071..dba031370ce8d15a46e8cef849eb2ce6e07a922c 100644 (file)
@@ -7,7 +7,7 @@
 #include "rk3399_mcu.h"
 
 /* Stack configuration */
-#define STACK_SIZE     0x00000100
+#define STACK_SIZE     0x00000040
 __attribute__ ((section(".co_stack")))
 unsigned long pstack[STACK_SIZE];
 
index af29a11142a67d817292a7bb10cb3d337f8acbab..39dfd113820816b090782ac841ba01b1f63afd13 100644 (file)
 
 #define SCR_SLEEPDEEP_SHIFT    (1 << 2)
 
-void handle_suspend(void)
+__attribute__((noreturn)) void main(void)
 {
        unsigned int status_value;
 
+       /*
+        * PMU sometimes doesn't clear power mode bit as it's supposed to due
+        * to a hardware bug. Make the M0 clear it manually to be sure,
+        * otherwise interrupts some cases with concurrent wake interrupts
+        * we stay asleep forever.
+        */
        while (1) {
                status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
                if (status_value) {
                        mmio_clrbits_32(PMU_BASE + PMU_PWRMODE_CON, 0x01);
-                       return;
+                       break;
                }
        }
 
-       /* m0 enter deep sleep mode */
-       mmio_setbits_32(M0_SCR, SCR_SLEEPDEEP_SHIFT);
+       /*
+        * FSM power secquence is .. -> ST_INPUT_CLAMP(step.17) -> .. ->
+        * ST_WAKEUP_RESET -> ST_EXT_PWRUP-> ST_RELEASE_CLAMP ->
+        * ST_24M_OSC_EN -> .. -> ST_WAKEUP_RESET_CLR(step.26) -> ..,
+        * INPUT_CLAMP and WAKEUP_RESET will hold the SOC not affect by
+        * power or other single glitch, but WAKEUP_RESET need work with 24MHz,
+        * so between RELEASE_CLAMP and 24M_OSC_EN, there have a chance
+        * that glitch will affect SOC, and mess up SOC status, so we
+        * addressmap_shared software clamp between ST_INPUT_CLAMP and
+        * ST_WAKEUP_RESET_CLR to avoid this happen.
+        */
+       while (1) {
+               status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+               if (status_value >= 17)  {
+                       mmio_setbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+                       break;
+               }
+
+       }
+
+       while (1) {
+               status_value = mmio_read_32(PMU_BASE + PMU_POWER_ST);
+               if (status_value >= 26)  {
+                       mmio_clrbits_32(PMU_BASE + PMU_SFT_CON, 0x02);
+                       break;
+               }
+       }
+
+       for (;;)
+               __asm__ volatile ("wfi");
 }
index 61849e5006475991ed4b2561e5452edd1d375237..3f258b7894b82f2de7badfb7423da9781c1929b9 100644 (file)
@@ -21,14 +21,6 @@ void m0_init(void)
        mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
        mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
 
-       /* set the execute address for M0 */
-       mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
-                     BITS_WITH_WMASK((M0_BINCODE_BASE >> 12) & 0xffff,
-                                     0xffff, 0));
-       mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
-                     BITS_WITH_WMASK((M0_BINCODE_BASE >> 28) & 0xf,
-                                     0xf, 0));
-
        /* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
        mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
 
@@ -46,6 +38,17 @@ void m0_init(void)
        mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
 }
 
+void m0_configure_execute_addr(uintptr_t addr)
+{
+       /* set the execute address for M0 */
+       mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
+                     BITS_WITH_WMASK((addr >> 12) & 0xffff,
+                                     0xffff, 0));
+       mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
+                     BITS_WITH_WMASK((addr >> 28) & 0xf,
+                                     0xf, 0));
+}
+
 void m0_start(void)
 {
        /* enable clocks for M0 */
index b313ec6af801c8a48c662e8709d9c382dc1a8961..cb323c482b931fc11fb8b07a6b94f161060cdac2 100644 (file)
 
 #define M0_BINCODE_BASE        ((uintptr_t)rk3399m0_bin)
 #define M0_PARAM_ADDR          (M0_BINCODE_BASE + PARAM_ADDR)
+#define M0PMU_BINCODE_BASE     ((uintptr_t)rk3399m0pmu_bin)
 
 /* pmu_fw.c */
 extern char rk3399m0_bin[];
 extern char rk3399m0_bin_end[];
 
+extern char rk3399m0pmu_bin[];
+extern char rk3399m0pmu_bin_end[];
+
 extern void m0_init(void);
 extern void m0_start(void);
 extern void m0_stop(void);
 extern void m0_wait_done(void);
+extern void m0_configure_execute_addr(uintptr_t addr);
 #endif /* __M0_CTL_H__ */
index 014d4047ca198cab4253f66219276f15d9ed427c..e136bbc9ea0d15ce8807dfa4c61bfa959a5172b8 100644 (file)
@@ -1064,12 +1064,6 @@ static void resume_gpio(void)
        }
 }
 
-static void m0_configure_suspend(void)
-{
-       /* set PARAM to M0_FUNC_SUSPEND */
-       mmio_write_32(M0_PARAM_ADDR + PARAM_M0_FUNC, M0_FUNC_SUSPEND);
-}
-
 void sram_save(void)
 {
        size_t text_size = (char *)&__bl31_sram_text_real_end -
@@ -1344,7 +1338,7 @@ int rockchip_soc_sys_pwr_dm_suspend(void)
        set_pmu_rsthold();
        sys_slp_config();
 
-       m0_configure_suspend();
+       m0_configure_execute_addr(M0PMU_BINCODE_BASE);
        m0_start();
 
        pmu_sgrf_rst_hld();
index d299116c6ac31487f0b9d58b661d8ff16e3bbcda..a09ad21e8796aaef10a06730b5c00598b5e24b8b 100644 (file)
@@ -5,9 +5,9 @@
  */
 
 /* convoluted way to make sure that the define is pasted just the right way */
-#define _INCBIN(file, sym) \
+#define _INCBIN(file, sym, sec) \
        __asm__( \
-               ".section .sram.incbin\n" \
+               ".section " #sec "\n" \
                ".global " #sym "\n" \
                ".type " #sym ", %object\n" \
                ".align 4\n" \
@@ -18,6 +18,7 @@
                #sym "_end:\n" \
        )
 
-#define INCBIN(file, sym) _INCBIN(file, sym)
+#define INCBIN(file, sym, sec) _INCBIN(file, sym, sec)
 
-INCBIN(RK3399M0FW, rk3399m0_bin);
+INCBIN(RK3399M0FW, rk3399m0_bin, ".sram.incbin");
+INCBIN(RK3399M0PMUFW, rk3399m0pmu_bin, ".pmusram.incbin");
index 85f4dc3341e298dc68cea40efb10ebf519ff41a8..528c15002aa36d3c4dc0ff885976d8d18f7055ef 100644 (file)
@@ -77,14 +77,21 @@ SECTIONS
                ASSERT(. == ALIGN(64 * 1024),
                        ".pmusram.entry request 64K aligned.");
                *(.pmusram.entry)
+
                __bl31_pmusram_text_start = .;
                *(.pmusram.text)
                *(.pmusram.rodata)
                __bl31_pmusram_text_end = .;
+
+               /* M0 start address request 4K align */
+               . = ALIGN(4096);
+               __pmusram_incbin_start = .;
+               *(.pmusram.incbin)
+               __pmusram_incbin_end = .;
+
                __bl31_pmusram_data_start = .;
                *(.pmusram.data)
                __bl31_pmusram_data_end = .;
-
        } >PMUSRAM
 }
 
index 3edbf89b779a65a2bae28a1eb608eb7f514e5e3e..044e797afefcfb2dbfd101d229f2fd65ae7e8465 100644 (file)
@@ -7,13 +7,6 @@
 #ifndef __M0_PARAM_H__
 #define __M0_PARAM_H__
 
-#ifndef __LINKER__
-enum {
-       M0_FUNC_SUSPEND = 0,
-       M0_FUNC_DRAM    = 1,
-};
-#endif /* __LINKER__ */
-
 #define PARAM_ADDR             0xc0
 
 #define PARAM_M0_FUNC          0x00
index 1997dfc4832be84fcd1c413936fcc1be048db143..fc386f05a3a844021383612e26dea0800e707572 100644 (file)
@@ -82,12 +82,15 @@ BUILD_M0            :=      ${BUILD_PLAT}/m0
 RK3399M0FW=${BUILD_M0}/${PLAT_M0}.bin
 $(eval $(call add_define,RK3399M0FW))
 
+RK3399M0PMUFW=${BUILD_M0}/${PLAT_M0}pmu.bin
+$(eval $(call add_define,RK3399M0PMUFW))
+
 HDCPFW=${RK_PLAT_SOC}/drivers/dp/hdcp.bin
 $(eval $(call add_define,HDCPFW))
 
 # CCACHE_EXTRAFILES is needed because ccache doesn't handle .incbin
 export CCACHE_EXTRAFILES
-${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW)
+${BUILD_PLAT}/bl31/pmu_fw.o: CCACHE_EXTRAFILES=$(RK3399M0FW):$(RK3399M0PMUFW)
 ${RK_PLAT_SOC}/drivers/pmu/pmu_fw.c: $(RK3399M0FW)
 
 ${BUILD_PLAT}/bl31/cdn_dp.o: CCACHE_EXTRAFILES=$(HDCPFW)